package com.smartcommunity.service.people.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.StringUtil;
import com.smartcommunity.api.engine.EngineApi;
import com.smartcommunity.base.bean.ExceptionCode;
import com.smartcommunity.base.bean.PeopleFaceVid;
import com.smartcommunity.base.common.CacheMap;
import com.smartcommunity.bean.constant.Constant;
import com.smartcommunity.bean.entity.User;
import com.smartcommunity.bean.enumeration.PeopleTypeEnum;
import com.smartcommunity.bean.enumeration.ResultCode;
import com.smartcommunity.bean.model.Pager;
import com.smartcommunity.bean.model.Result;
import com.smartcommunity.dao.device.DeviceDao;
import com.smartcommunity.dao.people.PeopleDao;
import com.smartcommunity.dao.sixEntity.SixEntityDao;
import com.smartcommunity.dao.tag.TagDao;
import com.smartcommunity.dao.vehicle.VehicleDao;
import com.smartcommunity.dao.village.HouseDao;
import com.smartcommunity.dao.village.VillageDao;
import com.smartcommunity.elasticsearch.base.impl.BasedataDataService;
import com.smartcommunity.elasticsearch.people.PeopleEsApi;
import com.smartcommunity.entity.people.*;
import com.smartcommunity.entity.people.dto.AddPeopleDto;
import com.smartcommunity.entity.people.dto.HouseDto;
import com.smartcommunity.entity.people.dto.UpdatePeopleDto;
import com.smartcommunity.entity.sixEnity.DataTypeStatistic;
import com.smartcommunity.entity.statistic.StatisticByTypeResp;
import com.smartcommunity.entity.tag.Tag;
import com.smartcommunity.entity.vid.SearchModel;
import com.smartcommunity.entity.vid.VidInfo;
import com.smartcommunity.entity.village.House;
import com.smartcommunity.entity.village.OrganizationVillage;
import com.smartcommunity.entity.village.SixStatisticsEntity;
import com.smartcommunity.es.common.EsBasedataEnum;
import com.smartcommunity.es.common.EsIndex;
import com.smartcommunity.es.common.EsRestUtils;
import com.smartcommunity.exception.BusinessException;
import com.smartcommunity.service.people.PeopleService;
import com.smartcommunity.service.tag.TagService;
import com.smartcommunity.service.vidInfo.impl.VidInfoServiceImpl;
import com.smartcommunity.service.village.impl.HouseService;
import com.smartcommunity.utils.ArrayUtils;
import com.smartcommunity.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @version V1.0
 * @ClassName: PeopleServiceImpl
 * @Description: 实有人口service类
 * @author: minsheng
 * @Date: 2019/3/4 10:02
 * @Company:
 */
@Service
@Slf4j
public class PeopleServiceImpl implements PeopleService {

    @Autowired
    private PeopleDao peopleDao;
    @Autowired
    private VillageDao villageDao;
    @Autowired
    private HouseDao houseDao;
    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private SixEntityDao sixEntityDao;
    @Autowired
    private VehicleDao vehicleDao;
    @Autowired
    TagService tagService;
    @Autowired
    TagDao tagDao;
    @Autowired
    HouseService houseService;
    @Autowired
    EngineApi engineApi;
    @Autowired
    VidInfoServiceImpl vidInfoService;
    @Autowired
    private EsRestUtils esRestUtils;
    @Autowired
    private PeopleEsApi peopleEsApi;
    @Autowired
    private BasedataDataService basedataDataService;

    @Override
    public Pager<People> getAllPeople(Map<String, Object> queryMap, int currentPage, int pageSize) {
        PageHelper.startPage(currentPage, pageSize);
        List<People> entryList = peopleDao.getAllPeople(queryMap);
        int total = (int) ((Page) entryList).getTotal();
        return new Pager<>(currentPage, pageSize, total, entryList);
    }

    /**
     * @param people
     * @return
     */
    public boolean checkPeopleParam(People people) {
        if (StringUtils.isBlank(people.getText()) && StringUtils.isBlank(people.getCredentialNo()) && StringUtils.isBlank(people.getBirthDateStart()) &&
                StringUtils.isBlank(people.getBirthDateEnd()) && StringUtils.isBlank(people.getNation()) && StringUtils.isBlank(people.getPhoneNo()) &&
                (people.getPeopleType() == null) && StringUtils.isBlank(people.getGender()) &&
                StringUtils.isBlank(people.getPeopleName()) && StringUtils.isBlank(people.getFeatureId()) && StringUtils.isBlank(people.getLabel())
                && StringUtils.isBlank(people.getDomicileAddress()) && (people.getIsVid() == null) && StringUtils.isBlank(people.getIdCardPic())) {
            return true;
        }
        return false;
    }




    /**
     * 人员列表
     *
     * @param people      人员对象
     * @param currentPage 当前页
     * @param pageSize    每页记录数
     * @return 人员列表
     */
    @SuppressWarnings("rawtypes")
    @Override
    public Pager<People> listPeoples(People people, int currentPage, int pageSize, String sortField, String sortModel) {
        long st = System.currentTimeMillis();
        Pager<People> pager = peopleEsApi.listPage(people, currentPage, pageSize, sortField, sortModel);
        List<People> entryList = pager.getList();

        //读出来后 关联mysql,用来更新标签 by whaijie
        List<Tag> allTag = tagDao.getTagList(null);
        for(People pp : entryList){
            if(pp.getLableList() == null){
                continue;
            }
            for(Tag tag:pp.getLableList()){
                Tag dbTag = allTag.stream().filter(m -> m.getId().equals(tag.getId())).findFirst().get();
                BeanUtils.copyProperties(dbTag,tag);
            }
        }

        long speedTime = System.currentTimeMillis() - st;
        log.info("2.实有人口列表查询耗时:" + speedTime + "ms");

        if (CollectionUtils.isNotEmpty(entryList)) {
            st = System.currentTimeMillis();
            //构建最后出现的天数,构建vidinfo信息
            bulidLastDay(entryList);
            //构建标签信息
            buildLabel(entryList);
            //构建小区住址信息
            buildAddress(entryList, people.getVillageCode());
            speedTime = System.currentTimeMillis() - st;
            log.info("3.构建数据耗时:" + speedTime + "ms");
            return new Pager<>(currentPage, pageSize, pager.getTotalRow(), entryList);
        }
        return new Pager<People>();
    }

    private void buildAddress(List<People> entryList, String villageCode) {
    	List<String> villageCodeList = new ArrayList<String>();
    	if(StringUtils.isNotEmpty(villageCode)) {
    		villageCodeList = Arrays.asList(villageCode.replaceAll("'", "").split(","));
    	}
    	//如果人员存在多个小区，这里只显示一个小区的信息
        for (People peo : entryList) {
            if(CollectionUtils.isNotEmpty(peo.getDetailAddress())) {
            	for(RealPeopleHouse realPeopleHouse : peo.getDetailAddress()) {
            		if(CollectionUtils.isEmpty(villageCodeList) || villageCodeList.contains(realPeopleHouse.getVillageCode())) {
            			peo.setVillageCode(realPeopleHouse.getVillageCode());
                    	peo.setBuildingNo(realPeopleHouse.getBuildingNo());
                    	peo.setUnitNo(realPeopleHouse.getUnitNo());
                    	peo.setHouseNo(realPeopleHouse.getHouseNo());
                    	peo.setResidenceAddress(realPeopleHouse.getDetailAddress());
                    	//填充迁出状态，跟随小区的状态
                        peo.setIsLeave(realPeopleHouse.getMove());
                    	break;
            		}
            	}
            }
        }
    }

    private void buildLabel(List<People> entryList) {
        //封装数据
        for (People people : entryList) {
        	if (CollectionUtils.isNotEmpty(people.getLableList())) {
        		people.setPeopleTag(people.getLableList());
                StringBuffer labels = new StringBuffer();
                for (Tag tag : people.getLableList()) {
                    labels.append(tag.getTagName()).append(",");
                }
                people.setLabel(labels.subSequence(0, labels.length() - 1).toString());
            }
        }
    }

    private void bulidLastDay(List<People> entryList) {
        if (entryList != null && entryList.size() > 0) {
            String vids = "";
            for (People p : entryList) {
                if (!com.smartcommunity.utils.StringUtils.isEmpty(p.getVid())) {
                    if ("".equals(vids)) {
                        vids = p.getVid();
                    } else {
                        vids = vids + "," + p.getVid();
                    }
                }
            }
            SearchModel model = new SearchModel();
            model.setVid(vids.split(","));
            model.setPage(0);
            model.setPageSize(entryList.size());
            List<VidInfo> list = vidInfoService.listVidInfo(model);
            if (list != null && list.size() > 0) {
                for (VidInfo vidInfo : list) {
                    if (entryList != null && entryList.size() > 0) {
                        for (People entry : entryList) {
                            if (vidInfo.getVid() != null && entry.getVid() != null && vidInfo.getVid().trim().equals(entry.getVid().trim())) {
                                Long lastTime = vidInfo.getLastLogTime();
                                if (lastTime != null) {
                                    int day = DateUtils.getDateDaySpace(new Date(), new Date(lastTime));
                                    entry.setLastDay(day);
                                    entry.setVidinfo(vidInfo);
                                }
                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * 人员列表
     *
     * @param str 参数
     * @return 人员列表
     */
    @SuppressWarnings("rawtypes")
    @Override
    public List<People> listPeoplesByVids(String str) {
        People people = new People();
        people.setVid(str);
        people.setStartRow(0);
        people.setEndRow(1000);
        List<People> entryList = peopleDao.listPeoples(people);
        return entryList;
    }

    @Override
    public List<People> listPeoplesByCardIds(String str) {
        People people = new People();
        people.setLabel(str);
        people.setStartRow(0);
        people.setEndRow(1000);
        List<People> entryList = peopleDao.listPeoples(people);
        return entryList;
    }

    @Override
    public List<People> listPeoplesByParam(Map<String, String> paramMap) {
        return peopleDao.listPeoplesByParam(paramMap);
    }

    /**
     * 人员数量
     *
     * @param people 人员对象
     * @return 人员数量
     */
    @Override
    public int countPeoples(People people) {
        return peopleDao.countPeoples(people);
    }


    /**
     *  从es分组统计数量
     * @param paramMap
     * @return
     */
    public List<? extends Terms.Bucket> getPeopleTypeForEs(Map<String, Object> paramMap){
        List<? extends Terms.Bucket> list = new ArrayList<>();
        String villageCode = paramMap.get("villageCode")!=null?paramMap.get("villageCode").toString().replaceAll("'",""):"";
        String indexs = basedataDataService.getIndexName(null);
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(StringUtils.isNotEmpty(villageCode)){
            queryBuilder.must(QueryBuilders.termsQuery("villageCode", villageCode.split(",")));
        }
        String aggName = "peopleTypeGroup";
        TermsAggregationBuilder countAggr = AggregationBuilders.terms(aggName).field("peopleType").size(10);
        try {
            //判断索引是否存在
            if (!esRestUtils.isIndexExists(indexs)) {
                return list;
            }
            SearchResponse resp  = esRestUtils.getClient().search(
                    new SearchRequest().indices(indexs).source(new SearchSourceBuilder()
                                    .query(queryBuilder)
                                    .aggregation(countAggr)
                                    .from(0).size(0)
                                    .timeout(new TimeValue(60, TimeUnit.SECONDS))
                            ), RequestOptions.DEFAULT);
            if (200 != resp.status().getStatus()) {
                log.error("ES请求失败，响应:{}", resp);
                return list;
            }
            list = ((ParsedLongTerms) resp.getAggregations().get(aggName)).getBuckets();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
        return list;
    }

    /**
     *  从es分组统计数量
     * @param paramMap
     * @return
     */
    public List<? extends Terms.Bucket> getResidentiaTypeForEs(Map<String, Object> paramMap){
        List<? extends Terms.Bucket> list = new ArrayList<>();
        String villageCode = paramMap.get("villageCode")!=null?paramMap.get("villageCode").toString().replaceAll("'",""):"";
        String indexs = basedataDataService.getIndexName(null);
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(StringUtils.isNotEmpty(villageCode)){
            queryBuilder.must(QueryBuilders.termsQuery("villageCode", villageCode.split(",")));
        }
        String aggName = "residentiaTypeGroup";
        TermsAggregationBuilder countAggr = AggregationBuilders.terms(aggName).field("residentiaType").size(10);
        try {
            //判断索引是否存在
            if (!esRestUtils.isIndexExists(indexs)) {
                return list;
            }
            SearchResponse resp  = esRestUtils.getClient().search(
                    new SearchRequest().indices(indexs).source(new SearchSourceBuilder()
                            .query(queryBuilder)
                            .aggregation(countAggr)
                            .from(0).size(0)
                            .timeout(new TimeValue(60, TimeUnit.SECONDS))
                    ), RequestOptions.DEFAULT);
            if (200 != resp.status().getStatus()) {
                log.error("ES请求失败，响应:{}", resp);
                return list;
            }
            list = ((ParsedLongTerms) resp.getAggregations().get(aggName)).getBuckets();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
        return list;
    }

    /**
     * 实有人口分类统计
     *
     */
    @Override
    public Map<String, Object> countPeopleByTypeEs(Map<String, Object> paramMap) {

        //初始化数据
        Map<Integer,DataTypeStatistic> map = new HashMap<>();
        for (Map.Entry<Integer, String> entry : CacheMap.PEOPLE_TYPE_MAP.entrySet()) {
            DataTypeStatistic dataTypeStatistic = new DataTypeStatistic();
            //类型名称
            dataTypeStatistic.setName(entry.getValue());
            //类型值
            Integer value = Integer.parseInt(entry.getKey()+"");
            dataTypeStatistic.setValue(value);
            map.put(value,dataTypeStatistic);
        }

        int peopleCount = 0;

        //从es分组统计人员数量
        for (Terms.Bucket plt : getPeopleTypeForEs(paramMap)){
            int type =  Integer.parseInt(plt.getKey().toString());
            int count = Integer.parseInt(String.valueOf(plt.getDocCount()));
            peopleCount += count;
            DataTypeStatistic dataTypeStatistic = map.get(type);
            if(dataTypeStatistic==null){
                continue;
            }
            dataTypeStatistic.setNum(count);
            //统计数量
            map.get(type).setNum(count);
        }

        //实有人口类别
        List<DataTypeStatistic> list = new ArrayList<>();
        for (Integer key : map.keySet()) {
            list.add(map.get(key));
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("peopleTypeRecord", list);

        //人员总数
        Map<String, Object> peopleRecord = new HashMap<>();
        peopleRecord.put("peopleCount", peopleCount);
        resultMap.put("peopleRecord", peopleRecord);
        return resultMap;
    }

    /**
     *人口居住类型分类统计
     */
    @Override
    public Map<String, Object> countResidentiaTypeEs(Map<String, Object> paramMap) {

        log.info("人口居住类型分类统计 map = {}", CacheMap.RESIDENTIA_TYPE_MAP);
        //初始化数据
        Map<Integer,DataTypeStatistic> map = new HashMap<>();
        for (Map.Entry<Integer, String> entry : CacheMap.RESIDENTIA_TYPE_MAP.entrySet()) {
            DataTypeStatistic dataTypeStatistic = new DataTypeStatistic();
            //类型名称
            dataTypeStatistic.setName(entry.getValue());
            //类型值
            Integer value = Integer.parseInt(entry.getKey()+"");
            dataTypeStatistic.setValue(value);
            map.put(value,dataTypeStatistic);
        }

        int peopleCount = 0;

        //从es分组统计人员数量
        for (Terms.Bucket plt : getResidentiaTypeForEs(paramMap)){
            log.info("人口居住类型分类统计，从es分组统计人员数量 {}",  getResidentiaTypeForEs(paramMap));
            int type =  Integer.parseInt(plt.getKey().toString());
            int count = Integer.parseInt(String.valueOf(plt.getDocCount()));
            peopleCount += count;
            DataTypeStatistic dataTypeStatistic = map.get(type);
            if(dataTypeStatistic==null){
                continue;
            }
            dataTypeStatistic.setNum(count);
            //统计数量
            map.get(type).setNum(count);
        }

        //居住类型类别
        List<DataTypeStatistic> list = new ArrayList<>();
        for (Integer key : map.keySet()) {
            list.add(map.get(key));
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("peopleTypeRecord", list);

        //人员总数
        Map<String, Object> peopleRecord = new HashMap<>();
        peopleRecord.put("peopleCount", peopleCount);
        resultMap.put("peopleRecord", peopleRecord);
        return resultMap;
    }

    /**
     * 实有人口分类统计
     *
     */
    @Override
    public Map<String, Object> countPeopleByType(Map<String, Object> paramMap) {

        int peopleCount = 0;
        //获取人员类型统计，从任务结果中获取
        List<SixStatisticsEntity> sixList = sixEntityDao.getCountByChildType(paramMap);
        //初始化数据
        Map<Integer,DataTypeStatistic> map = new HashMap<>();
        for (Map.Entry<Integer, String> entry : CacheMap.PEOPLE_TYPE_MAP.entrySet()) {
            DataTypeStatistic dataTypeStatistic = new DataTypeStatistic();
            //类型名称
            dataTypeStatistic.setName(entry.getValue());
            //类型值
            Integer value = Integer.parseInt(entry.getKey()+"");
            dataTypeStatistic.setValue(value);
            map.put(value,dataTypeStatistic);
        }
        //填充统计数量
        for (SixStatisticsEntity sixStatisticsEntity :sixList){
            int type = sixStatisticsEntity.getChildType();
            int count = sixStatisticsEntity.getCount();
            peopleCount += count;
            DataTypeStatistic dataTypeStatistic = map.get(type);
            if(dataTypeStatistic==null){
                continue;
            }
            dataTypeStatistic.setNum(count);
            //统计数量
            map.get(type).setNum(count);
        }
        //实有人口类别
        List<DataTypeStatistic> list = new ArrayList<>();
        for (Integer key : map.keySet()) {
            list.add(map.get(key));
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("peopleTypeRecord", list);

        //人员总数
        Map<String, Object> peopleRecord = new HashMap<>();
        peopleRecord.put("peopleCount", peopleCount);
        resultMap.put("peopleRecord", peopleRecord);
        return resultMap;
    }

    @Override
    public People getPeopleBaseInfo(Map<String, String> map, List<String> villageCodes) {
        People basePeopleInfo = peopleDao.getPeopleBaseInfo(map);
        if(basePeopleInfo == null){
            return null;
        }
        //添加人员类型
        basePeopleInfo.setPeopleTypeName(CacheMap.PEOPLE_TYPE_MAP.get(basePeopleInfo.getPeopleType()));

        //添加住址信息,人屋关系
        if (basePeopleInfo != null && StringUtil.isNotEmpty(basePeopleInfo.getCredentialNo())) {
            List<RealPeopleHouse> address = peopleDao.getPeopleDetailAddress(basePeopleInfo.getCredentialNo());
            if (CollectionUtils.isNotEmpty(address)) {
            	for(RealPeopleHouse realPeopleHouse:address) {
            		if(CollectionUtils.isEmpty(villageCodes) || villageCodes.contains(realPeopleHouse.getVillageCode())) {
            			realPeopleHouse.setHasPrivilege(true);
            		} 
            	}
                basePeopleInfo.setDetailAddress(address);
            }
        }
        //添加house信息
        if (basePeopleInfo != null && StringUtil.isNotEmpty(basePeopleInfo.getCredentialNo())) {
            Map<String, Object> queryParam = new HashMap<String, Object>();
            queryParam.put("ids", basePeopleInfo.getCredentialNo());
            List<House> address = houseDao.queryHouseAndPersonEx(queryParam);
            if (CollectionUtils.isNotEmpty(address)) {
                basePeopleInfo.setHouseList(address);
            }
        }
        //实有力量标签
        if (basePeopleInfo != null && StringUtil.isNotEmpty(basePeopleInfo.getCredentialNo())) {
            if (StringUtils.isNotEmpty(basePeopleInfo.getLabel())) {
                Map<String, Object> queryParam = new HashMap<String, Object>();
                queryParam.put("label", basePeopleInfo.getLabel());
                // queryParam.put("objectId", basePeopleInfo.getCredentialNo());
                List<Tag> peopleTag = tagDao.getPeopleTag(queryParam);
                if (CollectionUtils.isNotEmpty(peopleTag)) {
                    basePeopleInfo.setPeopleTag(peopleTag);
                    basePeopleInfo.setLableList(peopleTag);
                }
            }
        }

        //添加车辆信息
        if (basePeopleInfo != null && StringUtil.isNotEmpty(basePeopleInfo.getCredentialNo()) && StringUtil.isEmpty(basePeopleInfo.getPlateNo())) {
            map.put("credentialNo", basePeopleInfo.getCredentialNo());
            Map<String, String> vehicleMap = peopleDao.getVehicleByHouseNo(map);
            if (null != vehicleMap && vehicleMap.containsKey("plateNo")) {
                basePeopleInfo.setPlateNo(vehicleMap.get("plateNo"));
                basePeopleInfo.setHouseNo(vehicleMap.get("houseNo"));
                basePeopleInfo.setBuildingNo(vehicleMap.get("buildingNo"));
            }
        }
        if (null != basePeopleInfo && StringUtils.isNotBlank(basePeopleInfo.getVid())) {
            try {
                bulidLastDay(Collections.singletonList(basePeopleInfo));
            } catch (Exception e) {
                log.error("查询vid异常", e);
            }
        }
        return basePeopleInfo;
    }


    /**
     * 添加人员信息
     *
     * @param addPeopleDto 请求参数
     */
    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result insertPeople(AddPeopleDto addPeopleDto) {
        Map<String, Object> params = new HashMap<>(1);
        People people = new People();
        // 设置证件号
        String credentialNo = addPeopleDto.getCredentialNo();
        people.setCredentialNo(credentialNo);
        //根据证件号查看用户时候存在，如果存在则不添加
        params.put("credentialNo", credentialNo);
        int cdCount = peopleDao.queryPeopleByCd(params);
        if (cdCount >= 1) {
            return Result.error(ResultCode.PEOPLE_CREDENTIALNO_EXSIT);
        }
        // 设置人员姓名
        people.setPeopleName(addPeopleDto.getPeopleName());
        // 获取证件类型
        String credentialType = addPeopleDto.getCredentialType();
        // 证件类型中文
        String credentialTypeCN = StringUtils.isNotEmpty(CacheMap.CREDENTIAL_TYPE_MAP.get(credentialType))?CacheMap.CREDENTIAL_TYPE_MAP.get(credentialType):"";
        // 设置证件类型
        people.setCredentialType(credentialType);
        people.setCredentialTypeCN(credentialTypeCN);
        // 设置人员类型
        people.setPeopleType(Integer.valueOf(addPeopleDto.getPeopleType()));
        // 设置性别
        people.setGender(StringUtils.isNotEmpty(CacheMap.GENDER_MAP.get(addPeopleDto.getGenderCode())) ? CacheMap.GENDER_MAP.get(addPeopleDto.getGenderCode()) : "");
        // 设置性别编码，1-男性，2-女性
        Integer genderCode = StringUtils.isNotEmpty(addPeopleDto.getGenderCode()) ? Integer.parseInt(addPeopleDto.getGenderCode()) : 0;
        people.setGenderCode(genderCode);
        // 获取电话
        people.setPhoneNo(addPeopleDto.getPhoneNo());
        // 获取出生日期
        people.setBirthDate(addPeopleDto.getBirthDate());
        // 获取民族
        people.setNation(addPeopleDto.getNation());
        // 设置户籍地址
        people.setDomicileAddress(addPeopleDto.getDomicileAddress());
        // 获取籍贯
        people.setOrigin(addPeopleDto.getOrigin());
        // 获取照片地址
        people.setIdCardPic(addPeopleDto.getIdCardPic());
        //人员标签
        people.setLabel(addPeopleDto.getLabel());

        List<HouseDto> list = addPeopleDto.getHouseList();
        // 添加人房关系
        if (CollectionUtils.isNotEmpty(list)) {
            houseService.insertPeopleHouse(list);
        }

        // 入库人员信息
        List<People> peopleList = new ArrayList<>();
        peopleList.add(people);
        peopleDao.insertPeoples(peopleList);
        //入库ES:people
        wrapPeopleHouseList(people, list);
        wrapPeopleLabelList(people);
        peopleEsApi.saveOrUpdate(people, true);
        //更新vid
        if (StringUtils.isNotBlank(people.getIdCardPic())) {
            //更新FeatureId
            updateVidAndFeatureIdByEngine(people);
        }
        return Result.ok();
    }

	/**
     * 包装人房关系实体
     */
	private void wrapPeopleHouseList(People people, List<HouseDto> list) {
		List<RealPeopleHouse> houseList = new ArrayList<RealPeopleHouse>();
		if(CollectionUtils.isNotEmpty(list)) {
			list.forEach(item->{
				RealPeopleHouse house = new RealPeopleHouse();
				house.setVillageCode(item.getVillageCode());
				house.setBuildingNo(item.getBuildingNo());
				house.setUnitNo(item.getUnitNo());
				house.setHouseNo(item.getHouseNo());
				house.setCredentialNo(item.getCredentialNo());
				house.setDetailAddress(item.concatDetailAddress());
				houseList.add(house);
			});
		}
		people.setDetailAddress(houseList);
	}
	
	/**
     * 包装实口标签关系实体
     * @param people
     */
    private void wrapPeopleLabelList(People people) {
    	if(StringUtils.isNotEmpty(people.getLabel())) {
            Map<String, Object> queryParam = new HashMap<String, Object>();
            queryParam.put("label", people.getLabel());
            List<Tag> peopleTag = tagDao.getPeopleTag(queryParam);
            if (CollectionUtils.isNotEmpty(peopleTag)) {
            	people.setLableList(peopleTag);
            }
		}
	}

	/**
     * 删除实有人员
     *
     * @param credentialNos
     */
    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result deletePeople(String credentialNos) {
        String[] nos = credentialNos.split(",");
        List<String> noList = Arrays.asList(nos);
        List<People> peopleList = peopleDao.getPeopleByCredentialNo(noList);
        List<Long> featureIds = peopleDao.getFeatureIds(noList);
        for (People people : peopleList) {
            if (StringUtils.isNotBlank(people.getVid())) {
                Map<String, Object> map1 = new HashMap<>();
                map1.put("idCard", null);
                map1.put("name", null);
                Map<String, Object> map2 = new HashMap<>();
                map2.put("credentialNo", null);
                map2.put("peopleName", null);
                try {
                    esRestUtils.update(EsIndex.VIDINFO, people.getVid(), map1);
                    esRestUtils.update(EsIndex.BASEDATA, people.getVid()+Constant.SEPARATOR+ EsBasedataEnum.VID.getIntValue(), map2);
                } catch (Exception e) {
                    log.error("删除常口更新es里vid的身份证信息异常", e);
                }
            }
        }
        peopleDao.deletePeopleHouse(noList);
        peopleDao.deletePeople(noList);
        //删除关联车辆
        vehicleDao.deleteVehicleByCredentialNos(noList);
        peopleEsApi.batchDelete(noList);
        if(CollectionUtils.isNotEmpty(featureIds)) {
        	engineApi.deletePersons(featureIds);
        }
        return Result.ok();
    }

    /**
     * 更新人员新
     *
     * @param updatePeopleDto 请求参数
     * @return
     */
    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result updatePeople(UpdatePeopleDto updatePeopleDto) {
        //判断证件号码是否存在，如果存在提示证件号码已存在
        List<People> peopleList = peopleDao.queryPeopleByCredentialNo(updatePeopleDto.getCredentialNo(), updatePeopleDto.getPeopleId());
        if (peopleList != null && peopleList.size() > 0) {
            return Result.error(ResultCode.USER_UPDATE_PEOPLE_EXIST_ERROR);
        }

        //根据id获取更新前的人员信息
        People oldPeople = peopleDao.queryPeopleById(updatePeopleDto.getPeopleId());
        if (oldPeople == null) {
            return Result.error(ResultCode.DATA_LOSE);
        }
        //已置信人员，不能修改身份证号码
        if (!oldPeople.getCredentialNo().equals(updatePeopleDto.getCredentialNo()) && StringUtils.isNotEmpty(oldPeople.getVid())) {
            return Result.error(ResultCode.USER_UPDATE_PEOPLE_VID_ERROR);
        }

        People people = new People();

        //设置居住类型
        people.setResidentiaType(updatePeopleDto.getResidentiaType());
        // 设置人员id
        people.setId(Integer.parseInt(updatePeopleDto.getPeopleId()));
        // 设置人员姓名
        people.setPeopleName(updatePeopleDto.getPeopleName());
        // 设置证件号
        people.setCredentialNo(updatePeopleDto.getCredentialNo());
        // 获取证件类型
        String credentialType = updatePeopleDto.getCredentialType();
        // 证件类型中文
        String credentialTypeCN = StringUtils.isNotEmpty(CacheMap.CREDENTIAL_TYPE_MAP.get(credentialType)) ? CacheMap.CREDENTIAL_TYPE_MAP.get(credentialType) : "";

        // 设置证件类型
        people.setCredentialType(credentialType);
        people.setCredentialTypeCN(credentialTypeCN);

        // 设置性别
        people.setGender(StringUtils.isNotEmpty(CacheMap.GENDER_MAP.get(updatePeopleDto.getGenderCode())) ? CacheMap.GENDER_MAP.get(updatePeopleDto.getGenderCode()) : "");
        // 设置性别编码，1-男性，2-女性
        Integer genderCode = StringUtils.isNotEmpty(updatePeopleDto.getGenderCode()) ? Integer.parseInt(updatePeopleDto.getGenderCode()) : 0;
        people.setGenderCode(genderCode);

        // 设置出生日期
        people.setBirthDate(updatePeopleDto.getBirthDate());
        // 设置民族
        people.setNation(updatePeopleDto.getNation());
        // 设置户籍地址
        people.setDomicileAddress(updatePeopleDto.getDomicileAddress());
        // 设置人员类型
        people.setPeopleType(Integer.valueOf(updatePeopleDto.getPeopleType()));
        // 设置籍贯
        people.setOrigin(updatePeopleDto.getOrigin());
        // 设置电话
        people.setPhoneNo(updatePeopleDto.getPhoneNo());
        // 设置标签
        people.setLabel(updatePeopleDto.getLabel());
        // 设置照片地址
        String idCardPic = updatePeopleDto.getIdCardPic();
        people.setIdCardPic(idCardPic);

        // 设置照片地址 ,判断人员照片地址是否有修改
        if (StringUtils.isNotBlank(idCardPic) && !idCardPic.equals(oldPeople.getIdCardPic())) {
            //更新照片之前先删除vid服务里已存在的特征。
            List<Long> featureIds = new ArrayList<>();
            long featureId = Long.parseLong(oldPeople.getFeatureId());
            //判断特征id 是否有效
            if (Long.parseLong(oldPeople.getFeatureId()) > 0) {
                featureIds.add(featureId);
            }
            if (CollectionUtils.isNotEmpty(featureIds)) {
                engineApi.deletePersons(featureIds);
            }
            //更新照片的时候，更新标记特征
            people.setFeatureId("0");
        }

        // 更新人员信息
        peopleDao.updatePeople(people);
        // 更新人房关系
        List<HouseDto> list = updatePeopleDto.getHouseList();
        if (CollectionUtils.isNotEmpty(list)) {
            // 先删除之前的人房关系
            houseService.deleteRelPeopleHouse(oldPeople.getCredentialNo());
            // 再新增人房关系
            houseService.insertPeopleHouse(list);
        }

        //修改关联车辆
        Map<String, Object> recordMap = new HashMap<>();
        recordMap.put("peopleId", updatePeopleDto.getPeopleId());
        recordMap.put("peopleName", updatePeopleDto.getPeopleName());
        recordMap.put("idcardNo", updatePeopleDto.getCredentialNo());
        recordMap.put("contactTel", updatePeopleDto.getPhoneNo());
        vehicleDao.updateVehicleByPeopleId(recordMap);

        //有修改证件号码
        if(!people.getCredentialNo().equals(oldPeople.getCredentialNo())){
            people.setOldCredentialNo(oldPeople.getCredentialNo());
        }
        people.setFeatureId(oldPeople.getFeatureId());
        people.setVid(oldPeople.getVid());
        wrapPeopleHouseList(people, list);
        wrapPeopleLabelList(people);
        //入库ES:people
        peopleEsApi.saveOrUpdate(people, false);

        if (StringUtils.isNotBlank(idCardPic) && !idCardPic.equals(oldPeople.getIdCardPic())) {
            //更新FeatureId
            updateVidAndFeatureIdByEngine(people);
        }
        return Result.ok();
    }

    /**
     * 更新证件照
     *
     * @param people 请求参数，使用身份证与身份证图片字段
     * @return
     */
    @Override
    public void updatePeoplePic(People people) {
        //更新人员信息
        peopleDao.updatePeoplePic(people);
        //更新ES
        Map<String, Object> map = new HashMap<>();
        map.put("idCardPic", people.getIdCardPic());
        try {
        	peopleEsApi.update(people.getCredentialNo(), map);
        }catch(Exception e) {
        	log.error("更新证件照更新es异常,credentialNo:{},error:", people.getCredentialNo(), e);
        }
    }

    @Override
    public List<Map<String, Object>> listRealPeopleGroup(Map<String, Object> recordMap) {
        try {
            return peopleDao.listRealPeopleGroup(recordMap);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.PEOPLE_SQL_EXCEPTION_CODE, "按小区统计实有人口出错！");
        }
    }

    @Override
    public List<People> listAllPeoples(Map<String, String> paramMap) {
        try {
            return peopleDao.listAllPeoples(paramMap);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.PEOPLE_SQL_EXCEPTION_CODE, "根据条件查询人员信息出错！");
        }
    }

    @Override
    public int queryPeopleListCount(People people) {
        int i;
        i = peopleDao.countPeoples(people);
        return i;
    }


    /**
     * @Description: 根据组织ID统计人口数量
     * @param: [param]
     * @return: int
     * @auther: minsheng
     * @date: 2019/3/4 16:57
     */
    Map<String, OrganizationVillage> villageHashMap = new HashMap<>(1);

    @Override
    public int countPeopleByOrgId(Map<String, Object> param) {
        String rootId = String.valueOf(param.get("id"));
        StringBuilder sb = new StringBuilder();
        getLeafOrgId(Integer.parseInt(rootId), sb);
        String ids = sb.toString();
        if (StringUtils.isNotBlank(ids)) {
            ids = StringUtils.substringBeforeLast(ids, ",");
        } else {
            ids = "null";
        }
        param.put("ids", ids);
        int i = peopleDao.countPeopleByOrgId(param);
        return i;
    }

    /**
     * 查询小区内所有的前科人员
     *
     * @param param
     * @return
     */
    @Override
    public List<People> listExCriminalByVillage(Map<String, Object> param) {
        return peopleDao.listExCriminalByVillage(param);
    }

    /**
     * @Description:
     * @param: [param]
     * @return: void
     * @auther: minsheng
     * @date: 2019/3/5 13:59
     */
    private void getOrganizationVillageByChildrenId(Map<String, Object> param) {
        try {
            List<OrganizationVillage> organizationList = null;
            String id = String.valueOf(param.get("id"));
            if (id != null) {
                organizationList = villageDao.listOrganizationVillageByChildrenId(Integer.valueOf(id));
            }
            if (organizationList.size() > 0) {
                for (OrganizationVillage organization : organizationList) {
                    villageHashMap.put(String.valueOf(organization.getId()), organization);
                    // 递归遍历子组织区划
                    param.put("id", organization.getId());
                    getOrganizationVillageByChildrenId(param);
                }
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.VILLAGE_SQL_EXCEPTION_CODE, "获得子组织区划及小区信息出错:" + e);
        }
    }

    /**
     * 获取行政区划叶子节点的id集合
     *
     * @param parentId 当前行政区划id
     * @param sb       集合对象
     */
    private void getLeafOrgId(Integer parentId, StringBuilder sb) {
        try {
            List<OrganizationVillage> organizationList = null;
            if (parentId != null) {
                organizationList = villageDao.listOrganizationVillageByChildrenId(parentId);
            }
            if (CollectionUtils.isNotEmpty(organizationList)) {
                for (OrganizationVillage organization : organizationList) {
                    // 递归遍历子组织区划
                    getLeafOrgId(organization.getId(), sb);
                }
            } else {
                sb.append("'").append(parentId).append("'").append(",");
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.VILLAGE_SQL_EXCEPTION_CODE, "获得行政区划叶子节点出错:" + e);
        }
    }


    /**
     * @param vid
     * @param topN
     * @return
     * @throws Exception
     * @Title: vidShowCameraCount
     * @Description: 摄像机抓拍规律（总频次）
     */
    @Override
    public List<JSONObject> vidShowCameraCount(String vid, int topN) {
        // 返回前端信息
        List<JSONObject> listInfo = new ArrayList<>();
        // 接口调用查询对应vid信息
//        listInfo = esApi.vidCameraGroupCountTopN(Long.parseLong(vid), topN);
        listInfo = null;
        if (CollectionUtils.isNotEmpty(listInfo)) {
            for (JSONObject info : listInfo) {

                //根据cameraId获取相机名称
                String cameraName = deviceDao.getCameraNameByKey(info.get("cameraId").toString());
                if (StringUtils.isNotEmpty(cameraName)) {
                    info.put("cameraName", cameraName);
                }
            }
        }
        return listInfo;
    }


    /**
     * @param vid
     * @return
     * @Title: vidLast7DayCount
     * @Description: 查询vid最近7天抓拍次数
     */
    @Override
    public List<JSONObject> vidLast7DayCount(Long vid) {
        List<JSONObject> listInfo = new ArrayList<JSONObject>();
        try {
            if (vid != null && vid != 0) {
//                listInfo = esApi.vidLast7DayCount(vid);
                listInfo = null;
            }
        } catch (Exception e) {
            log.error("PeopleServiceImpl:vidLast7DayCount error ,vid:{} ,e:",vid,e);
            log.error("查询vid最近7天抓拍次数错误");
        }
        return listInfo;
    }


    /**
     * 获取人脸VID信息
     *
     * @param
     * @return
     */
    @Override
    public PeopleFaceVid getPeopleFaceVid(Long vid) {
        try {
            if (vid != null && vid != 0) {
//                JSONObject jsonObject = esApi.queryVidInfo(vid);
                JSONObject jsonObject = null;
                if (jsonObject != null && jsonObject.size() > 0) {
                    PeopleFaceVid faceVid = JSONObject.parseObject(jsonObject.toString(), PeopleFaceVid.class);
                    return faceVid;
                }
            }
        } catch (Exception e) {
            log.error("获取人员VID信息失败,vid:{}",vid, e);
        }
        return null;
    }

    @Override
    public People queryPeopleBaseInfo(String credentialNo) {
        return peopleDao.queryPeopleBaseInfo(credentialNo);
    }

    @Override
    public Integer countByTagGroup(String villageCode, String groupId) {
        return peopleDao.countByTagGroup(villageCode, groupId);
    }

    @Override
    public Map<String, Object> countByTag(Map<String, Object> param) {
        Map<String, Object> resultMap = new HashMap<>(1);
        List<Tag> tagList = tagDao.countByTag(param);
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map;
        for (Tag tag : tagList) {
            map = new HashMap<>(2);
            map.put("name", tag.getTagName());
            map.put("num", tag.getTagId());
            list.add(map);
        }
        resultMap.put("labelRecord", list);
        return resultMap;
    }


    @Override
    public List<People> queryLiveTogetherPeople(String credentialNo) {
        List<People> peopleList = new ArrayList<>();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("ids", credentialNo);
        //查询当前人员拥有的房屋 
        List<House> houseList = houseDao.queryHouseAndPersonWithoutMoveout(param);
        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                Map<String, Object> peopleParam = new HashMap<String, Object>();
                peopleParam.put("villageCode", house.getVillageCode());
                peopleParam.put("buildingNo", house.getBuildingNo());
                peopleParam.put("unitNo", house.getUnitNo());
                peopleParam.put("houseNo", house.getHouseNo());
                List<Map> peopleMapList = houseDao.listPeople(peopleParam);
                if (CollectionUtils.isNotEmpty(peopleMapList)) {
                    for (Map peopleMap : peopleMapList) {
                        People people = new People();
                        if (credentialNo.equals(peopleMap.get("credentialNo"))) {
                            continue;
                        }
                        if (null != peopleMap.get("credentialNo")) {
                            people.setCredentialNo(peopleMap.get("credentialNo").toString());
                        }
                        if (null != peopleMap.get("peopleName")) {
                            people.setPeopleName(peopleMap.get("peopleName").toString());
                        }
                        if (null != peopleMap.get("idCardPic")) {
                            people.setIdCardPic(peopleMap.get("idCardPic").toString());
                        }
                        if (null != peopleMap.get("gender")) {
                            people.setGender(peopleMap.get("gender").toString());
                        }
                        if (null != peopleMap.get("genderCode")) {
                            people.setGenderCode(Integer.valueOf(peopleMap.get("genderCode").toString()));
                        }
                        people.setLabel("同住");
                        people.setVillageCode(house.getVillageCode());
                        people.setBuildingNo(house.getBuildingNo());
                        people.setUnitNo(house.getUnitNo());
                        people.setHouseNo(house.getHouseNo());
                        peopleList.add(people);
                    }
                }
            }
        }
        return peopleList;
    }

    @Override
    public StringBuilder getLeafOrgIds(Integer parentId, StringBuilder sb) {
        List<Integer> orgIds = peopleDao.getOrgId(parentId);
        if (CollectionUtils.isEmpty(orgIds)) {
            sb.append("'").append(parentId).append("'").append(",");

            return sb;
        }
        for (Integer id : orgIds) {
            getLeafOrgIds(id, sb);
        }

        return sb;
    }

    @Override
    public int countRealPeoples(Map<String, Object> params) {
        return peopleDao.countRealPeoples(params);
    }

    @Override
    public List<VidPeopleSense> queryPeopleCount(Map<String, Object> params) {
        return peopleDao.queryPeopleCount(params);
    }

    @Override
    public void syncPeopleVid() {
        try {
            long st = System.currentTimeMillis();
            int totalCount = peopleDao.getNoVidPeopleCount();
            int pageSize = 50000;
            int totalPage = (totalCount + pageSize - 1) / pageSize;
            for (int i = 1; i <= totalPage; i++) {
                int startRow = i > 0 ? (i - 1) * pageSize : 0;
                List<String> ids = peopleDao.getNoVidPeople(startRow, pageSize);
                log.info("正在从vid同步置信信息到社区实有人口表,总数{}正在处理{}-{}数据", totalCount, startRow, pageSize);
                if (ids == null || ids.size() == 0) {
                    continue;
                }
                long speedTime = System.currentTimeMillis() - st;
                log.info("数据库查询耗时{}毫秒", speedTime);
                int len = 100;
                //通过身份证查询vid信息使用的是get方式，url长度有限制，暂时使用10个身份证条件
                if (ids.size() > len) {
                    List<List<String>> splitIds = ArrayUtils.splitList(ids, len);
                    int j = 0;
                    for (List<String> cardIds : splitIds) {
                        try {
                            updatePeopleVid(cardIds);
                            j = j + 1;
                            log.info("正在从vid同步置信信息到社区实有人口表,总数:{},每页条数:{},当前页数:{}", ids.size(), len, j);
                        } catch (BusinessException e) {
                            log.error("从vid同步置信信息到社区实有人口ES失败！", e);
                        } catch (Exception e) {
                            log.error("从vid同步置信信息到社区实有人口表失败！", e);
                        }
                    }
                } else {
                    updatePeopleVid(ids);
                    log.info("正在从vid同步置信信息到社区实有人口表,总数:{}", ids.size());
                }
            }
        } catch (Exception e) {
            log.error("从vid同步置信信息到社区实有人口表失败！", e);
        }
    }

    private void updatePeopleVid(List<String> cardIds) throws BusinessException {
        String[] ids = cardIds.toArray(new String[cardIds.size()]);
        log.debug("ids:{}",ids!=null?ids.length:0);
        //获取对应的人员的信息
        Result result = engineApi.getVidPersonsByIdCard(ids);
        //更新没有vid的人员的vid信息
        if (result.getData() != null) {
            List<Map<String, Object>> list = JSONArray.parseObject(result.getData().toString(), List.class);
            log.debug("list:{}",list!=null?list.size():0);
            if (!CollectionUtils.isEmpty(list)) {
                Set<String> vidSet = new HashSet<>();
                for (Map<String, Object> tmp : list) {
                    String vid = tmp.get("vid") == null ? null : tmp.get("vid").toString();
                    vidSet.add(vid);
                }
                List<Map<String, Object>> vidExistList = new ArrayList<>();
                try {
                    //查询vidinfo存在的vid，将vid引擎存在 但vidinfo不存在的数据过滤掉。
                    final List<Map<String, Object>> existVidList = esRestUtils.getDataById(new String[]{EsIndex.VIDINFO}, new ArrayList<>(vidSet));
                    log.debug("vidinfo list :{}",existVidList!=null?existVidList.size():0);

                    for (Map<String, Object> listmap : list) {
                        for (Map<String, Object> map : existVidList) {
                            if (listmap.get("vid") != null && listmap.get("vid").toString().equals(map.get("vid").toString())) {
                                vidExistList.add(listmap);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("查询vidinfo存在的vid异常", e);
                }
                log.debug("vid exist vidinfo List :{}",vidExistList!=null?vidExistList.size():0);

                if (!CollectionUtils.isEmpty(vidExistList)) {
                    //更新ES
                    Map<String, Map<String, Object>> esUpdateMap = new HashMap<String, Map<String, Object>>();
                    for (Map<String, Object> tmp : vidExistList) {
                        String vid = tmp.get("vid") == null ? null : tmp.get("vid").toString();
                        String credentialNo = tmp.get("idcard") == null ? null : tmp.get("idcard").toString();
                        if (StringUtils.isNotEmpty(credentialNo)) {
                            Map<String, Object> valueMap = new HashMap<>();
                            valueMap.put("vid", vid);
                            esUpdateMap.put(credentialNo + Constant.SEPARATOR + EsBasedataEnum.PEOPLE.getIntValue(), valueMap);
                        }
                    }
                    /**
                     * 先保存es，保证数据都同步到了es中
                     */
                    if (!org.springframework.util.CollectionUtils.isEmpty(esUpdateMap)) {
                        peopleEsApi.batchUpdate(esUpdateMap);
                        log.info("es batchUpdate success {}",esUpdateMap.size());
                    }
                    peopleDao.updateVidByNo(vidExistList);
                    log.info("mysql updateVidByNo success {}",vidExistList.size());
                }
            }
        } else {
            log.error("正在同步实有库vid,没有查询到实有人口的vid {}", cardIds);
        }
    }

    @Override
    public List<People> getPeopleByName(String name) {
        if (StringUtils.isNotBlank(name)) {
            return peopleDao.getPeopleByName(name);
        } else {
            return null;
        }
    }

    @Override
    public List<People> getPeopleByCredentialNo(List<String> credentialNos) {
        if (CollectionUtils.isNotEmpty(credentialNos)) {
            return peopleDao.getPeopleByCredentialNo(credentialNos);
        } else {
            return null;
        }
    }

    /**
     * 从引擎同步Vid和特征id（添加和修改人员时使用）
     *
     * @param idcardNoList
     */
    @Override
    public void updateVidAndFeatureIdByEngine(List<String> idcardNoList) {
        if (idcardNoList != null && idcardNoList.size() > 0) {
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                    List<People> peoples = peopleDao.getPeopleByCredentialNo(idcardNoList);
                    if (peoples != null && peoples.size() > 0) {
                        //1.同步人员信息到VID引擎
                        for (People people : peoples) {
                            updateVidAndFeatureIdByEngine(people);
                            Thread.sleep(1000);
                        }
                    }
                } catch (Exception e) {
                    log.error("同步人员信息到VID引擎异常", e);
                }
            }).start();
        }
    }

    /**
     * 从引擎同步Vid和特征id（添加和修改人员时使用）
     *
     * @param people
     */
    public void updateVidAndFeatureIdByEngine(People people) {
        if (people != null){
            if(people.getId()==null){
                List<String> idcardNoList = new ArrayList<>();
                idcardNoList.add(people.getCredentialNo());
                List<People> peoples = peopleDao.getPeopleByCredentialNo(idcardNoList);
                if (peoples != null && peoples.size() > 0) {
                    people= peoples.get(0);
                }else {
                    return;
                }
            }
            try {
                Map<String, Object> person = new HashMap<>();
                person.put("id", people.getId());
                //此处图片并非完整地址，需要补充完整
                if (!org.springframework.util.StringUtils.isEmpty(people.getIdCardPic())) {
                    person.put("pic", people.getIdCardPic());
                    person.put("idCard", people.getCredentialNo());
                    person.put("name", people.getPeopleName());
                    // todo 算法交互  新增人口
                    Result result = engineApi.uploadPerson(person);
                    if (result.getData() != null) {
                        Long featureId = Long.valueOf(result.getData().toString());
                        Long vid = null;
                        String[] ids = {people.getCredentialNo()};
                        //获取对应的人员的信息
                        Result vidResult = engineApi.getVidPersonsByIdCard(ids);
                        //更新没有vid的人员的vid信息
                        if (vidResult.getData() != null) {
                            List<Map<String, Object>> resultDataList = JSONArray.parseObject(vidResult.getData().toString(), List.class);
                            if (!CollectionUtils.isEmpty(resultDataList)) {
                                vid = resultDataList.get(0).get("vid") == null ? null : Long.valueOf(resultDataList.get(0).get("vid").toString());
                            }
                        }
                        peopleDao.updatePeopleVidAndFeatureId(people.getCredentialNo(), featureId, vid);
                        //更新ES
                        Map<String, Object> valueMap = new HashMap<String, Object>();
                        valueMap.put("vid", vid);
                        valueMap.put("featureId", featureId);
                        peopleEsApi.update(people.getCredentialNo(), valueMap);
                    }
                }
            } catch (Exception e) {
                log.error("同步人员信息到VID引擎异常,人员信息：{}", people.toString(), e);
            }

        }
    }



    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result moveIn(RealPeopleHouseMove realPeopleHouseMove, User user) {
    	realPeopleHouseMove.setMove(1);
        List<RealPeopleHouse> realPeopleHouseList = getPeopleHouseByMove(realPeopleHouseMove);
        if (CollectionUtils.isEmpty(realPeopleHouseList)) {
            HouseDto houseDto = new HouseDto();
            houseDto.setCredentialNo(realPeopleHouseMove.getCredentialNo());
            houseDto.setVillageCode(realPeopleHouseMove.getVillageCode());
            houseDto.setBuildingNo(realPeopleHouseMove.getBuildingNo());
            houseDto.setUnitNo(realPeopleHouseMove.getUnitNo());
            houseDto.setHouseNo(realPeopleHouseMove.getHouseNo());
            houseDao.insertPeopleHouse(Collections.singletonList(houseDto));
        } else {
            boolean hasMoveIn = true;
            for (RealPeopleHouse realPeopleHouse : realPeopleHouseList) {
                if (realPeopleHouseMove.getMove().intValue() != realPeopleHouse.getMove()) {
                    hasMoveIn = false;
                }
            }
            if (hasMoveIn) {
                return Result.error(ResultCode.HOUSE_HAS_MOVE_IN);
            } else {
                realPeopleHouseList.forEach(o -> o.setMove(realPeopleHouseMove.getMove()));
                houseDao.updatePeopleHouseMoveField(realPeopleHouseList);
            }
        }
        // 迁入
        realPeopleHouseMove.setOperateUserId(user.getId().toString());
        realPeopleHouseMove.setOperateUserName(user.getShowName());
        houseDao.insertPeopleHouseMove(realPeopleHouseMove);
        updateEsPeopleHouse(realPeopleHouseMove.getCredentialNo());
        return Result.ok();
    }

    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result moveOut(RealPeopleHouseMove realPeopleHouseMove, User user) {

    	//获取实有人口名下所有的房屋信息
        List<RealPeopleHouse> realPeopleHouseList = getPeopleHouseByMove(realPeopleHouseMove);
        if (CollectionUtils.isEmpty(realPeopleHouseList)) {
            return Result.error(ResultCode.HOUSE_NOT_EXSIT);
        } else {
            realPeopleHouseMove.setMove(2);
            realPeopleHouseList.forEach(o -> o.setMove(realPeopleHouseMove.getMove()));
            houseDao.updatePeopleHouseMoveField(realPeopleHouseList);
        }
        // 迁出
        realPeopleHouseMove.setOperateUserId(user.getId().toString());
        realPeopleHouseMove.setOperateUserName(user.getShowName());
        houseDao.insertPeopleHouseMove(realPeopleHouseMove);
        updateEsPeopleHouse(realPeopleHouseMove.getCredentialNo());
        return Result.ok();
    }
    
    /**
     * 修改es-basedata索引的人房关系
     * @param realPeopleHouseMove
     */
    private void updateEsPeopleHouse(String credentialNo) throws BusinessException {
    	EsPeopleEntity esPeople = peopleEsApi.getDataById(credentialNo);
    	if(esPeople!=null) {
    		List<RealPeopleHouse> address = peopleDao.getPeopleDetailAddress(credentialNo);
    		esPeople.setDetailAddress(address);
    		peopleEsApi.saveOrUpdate(esPeople, false);
    	}
    }

    @Override
    public List<RealPeopleHouseMove> moveList(String credentialNo) {
        // 迁入迁出列表
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("credentialNo", credentialNo);
        return houseDao.selectPeopleHouseMoveList(queryMap);
    }

    @Override
    public Result bindVid(PeopleSearchModel peopleSearch) {
        Map<String, Object> info = new HashMap<>();
        info.put("idcard", peopleSearch.getCredentialNo());
//        info.put("name", "");
        info.put("vid", peopleSearch.getVid());
        Result<List<Map<String, Object>>> result = engineApi.binds(Collections.singletonList(info));
        if (!CollectionUtils.isEmpty(result.getData())) {
            List<Map<String, Object>> data = result.getData();
            for (Map<String, Object> map : data) {
                if (peopleSearch.getVid().equals(map.get("vid"))) {
                    if ((boolean) map.get("_success")) {
                    } else {
                    }
                    log.info("vid绑定结果:{}", JSON.toJSONString(result));
                    Map<String, Object> personVid = new HashMap<>();
                    personVid.put("vid", peopleSearch.getVid());
                    personVid.put("idcard", peopleSearch.getCredentialNo());
                    peopleDao.updateVidByNo(Collections.singletonList(personVid));
                    Map<String, Object> valueMap = new HashMap<>();
                    valueMap.put("vid", peopleSearch.getVid());
                    try {
                    	peopleEsApi.update(peopleSearch.getCredentialNo(), valueMap);
                    }catch(Exception e) {
                    	log.error("vid绑定更新es异常,credentialNo:{},error:", peopleSearch.getCredentialNo(), e);
                    }
                    break;
                }
            }
        }
        System.out.println(JSON.toJSONString(result));
        return Result.ok();
    }

    @Override
    public Result unbindVid(PeopleSearchModel peopleSearch) {
        Map<String, Object> info = new HashMap<>();
        info.put("idcard", peopleSearch.getCredentialNo());
        info.put("name", "");
        info.put("vid", peopleSearch.getVid());
        Result<List<Map<String, Object>>> result = engineApi.unbinds(Collections.singletonList(info));
        if (!CollectionUtils.isEmpty(result.getData())) {
            List<Map<String, Object>> data = result.getData();
            for (Map<String, Object> map : data) {
                if (peopleSearch.getVid().equals(map.get("vid"))) {
                    if ((boolean) map.get("_success")) {
                    } else {
                    }
                    log.info("vid解除绑定结果:{}", JSON.toJSONString(result));
                    Map<String, Object> personVid = new HashMap<>();
                    personVid.put("vid", null);
                    personVid.put("idcard", peopleSearch.getCredentialNo());
                    peopleDao.updateVidByNo(Collections.singletonList(personVid));
                    Map<String, Object> valueMap = new HashMap<>();
                    valueMap.put("vid", null);
                    try {
                    	peopleEsApi.update(peopleSearch.getCredentialNo(), valueMap);
                    }catch(Exception e) {
                    	log.error("vid解绑更新es异常,credentialNo:{},error:", peopleSearch.getCredentialNo(), e);
                    }
                    break;
                }
            }
        }
        return Result.ok();
    }

    private List<RealPeopleHouse> getPeopleHouseByMove(RealPeopleHouseMove realPeopleHouseMove) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("credentialNo", realPeopleHouseMove.getCredentialNo());
        queryMap.put("villageCode", realPeopleHouseMove.getVillageCode());
//        queryMap.put("buildingNo", realPeopleHouseMove.getBuildingNo());
//        queryMap.put("unitNo", realPeopleHouseMove.getUnitNo());
//        queryMap.put("houseNo", realPeopleHouseMove.getHouseNo());
        //查找这个人名下的房屋
        return houseDao.selectRelPeopleHouse(queryMap);
    }

    @Override
    public Integer getAllPeopleCount() {
        return peopleDao.getAllPeopleCount(null);
    }
    @Override
    public List<StatisticByTypeResp> getPeopleTypeCount() {
        List<StatisticByTypeResp> statisticByTypeResps = peopleDao.getPeopleTypeCount();
        if(CollectionUtils.isNotEmpty(statisticByTypeResps)){
            statisticByTypeResps.forEach(statisticByType -> {
                statisticByType.setTypeName(PeopleTypeEnum.getNamebyValue(statisticByType.getType()));
            });
        }
        return statisticByTypeResps;
    }

    /**
	 * 实有人口-数据迁移到ES-basedata索引
	 */
	@Override
	public Result syncDataToEs(String villageCode, String buildingNo) throws Exception {
		int totalCount = peopleDao.getAllPeopleCountForEs(villageCode, buildingNo);
		int pageSize = 10000;
		int totalPage = totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
		People people = new People();
		for(int currentPage=1;currentPage<=totalPage;currentPage++) {
	        people.setStartRow((currentPage-1)*pageSize);
	        people.setEndRow(pageSize);
	        people.setVillageCode(villageCode);
	        people.setBuildingNo(buildingNo);
	        List<People> peopleList = peopleDao.listPeoplesForEs(people);
	        if(CollectionUtils.isNotEmpty(peopleList)) {
	        	peopleList.forEach(item->{
	        		List<RealPeopleHouse> houses = item.getDetailAddress();
	        		houses.forEach(house->{
	        			house.setDetailAddress(house.concatDetailAddress());
	        		});
	        		wrapPeopleLabelList(item);
	        	});
	        	log.info("--------实有人口-数据迁移到ES-basedata索引:第{}页,数据总量:{}--------", currentPage, peopleList.size());
	        	peopleEsApi.batchSaveOrUpdatePeople(peopleList, false);
	        }
		}
		return Result.ok();
	}
	
	/**
     * 人员列表
     *
     * @param people      人员对象
     * @param currentPage 当前页
     * @param pageSize    每页记录数
     * @return 人员列表
     */
    @Override
    public Pager<People> listPeoplesForFullSearch(People people, int currentPage, int pageSize) {
        Pager<People> pager = peopleEsApi.listPage(people, currentPage, pageSize);
        List<People> entryList = pager.getList();
        if (CollectionUtils.isNotEmpty(entryList)) {
            //构建标签信息
            buildLabel(entryList);
            //构建小区住址信息
            buildAddress(entryList, people.getVillageCode());
            return new Pager<>(currentPage, pageSize, pager.getTotalRow(), entryList);
        }
        return new Pager<People>();
    }

    /**
     * 新增人房关系
     */
	@Override
	@Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
	public Result insertPeopleHouse(List<HouseDto> list) {
		if (CollectionUtils.isNotEmpty(list)) {
            houseService.insertPeopleHouse(list);
            Set<String> credentialNos = new HashSet<>();
            for(HouseDto houseDto:list) {
            	credentialNos.add(houseDto.getCredentialNo());
            }
            for(String credentialNo:credentialNos) {
            	updateEsPeopleHouse(credentialNo);
            }
        }
		return Result.ok();
	}
}